/*
 * Snippet.js defines snippet base class
 * 
 * Snippet is a single piece of dynamic content on the view
 * Snippets are used to keep view constructors simpler - and
 * to separate content from application logics as much as
 * possible
 * 
 * Snippet can have a built in feature of rendering different
 * content with and without data. This is - again - to help
 * everyday tasks with Ajax-based applications 
 * 
 * Snippets are used i.e. in PlaceView.js
 * 
 */

/**
 * @param {String} id Id of the DOM element to attach this Snippet to. (optional)
 * @param {Object} params Hash of parameters for the Snippet. (optional)
 */
var Snippet = Class.create({
    initialize: function(id, params)  {
        params = params || {};
        this.dom = null;
        this.id = null;
        this.data = params.data || {};
        this.events = {};

        this.onData = {
            template : [],
            doUse: undefined
        };
        this.onDefault = {
            template : []
        };

        if(id) {
            this.setDom(id);
        }
    },
	
    setDom: function(id) {
        if(!id) {
            throw "ID is not set for setDom -function";
            return;
        }
        var tempDom = document.getElementById(id);
        if(tempDom != null) {
            this.dom = tempDom;
            this.id = id;
        } else {
            throw "No id: " + id + " found";
            return;
        }
    },

    updateDom: function () {
        this.setDom(this.id);
    },

    setData: function (data) {
        if (!data) {
            throw "No data parameter set for setData -function";
            return;
        }
        this.data = data;
    },

    clearData: function () {
        this.data = {};
    },

    output: function (source) {
        var output = "";

        for (var i = 0, l = source.template.length; i < l; i++) {
            var item = source.template[i];
            switch (typeof item) {
                case 'string':
                case 'number':
                    output += item;
                    break;
                case 'object':
                    try {
                        output += item.fn.apply( item.base, item.params ); 
                    } catch (e) {
                        util.log("{Snippet.prototype.output} exception when trying to handle object");
                        util.log(item);
                        util.log(e);
                    }
                    break;
            }
        }

        return output;
    },

    handler: function () {
        if (this.data &&
            ((typeof this.onData.doUse == 'function' && this.onData.doUse()) ||
              (typeof this.onData.doUse != 'function' && this.onData.doUse))) {
            return this.output(this.onData);
        }

        return this.output(this.onDefault);
    },

    html: function () {
        return this.handler();
    },

    rewrite: function () {
        if (this.dom != null) {
            this.dom.innerHTML = this.html();
        } else {
            throw "DOM element is not set, use setDom(id) first";
            return;
        }
    },

    registerEvents: function (events) {
        for(var event in events) {
            this.dom.addEventListener(event, events[event], true)
        }
    }
});